import GameFrameworkLinkedList from "../../Utils/GameFrameworkLinkedList";
import LinkListNode from "../../Utils/LinkList";
import GameFrameworkModule, { CreateInstance } from "./GameFrameworkModule";
import EventManager from "../Event/EventManager";

export default class GameFrameworkEntry {
    private static readonly s_GameFrameworkModules:GameFrameworkLinkedList<GameFrameworkModule>  = new GameFrameworkLinkedList<GameFrameworkModule>();


    public static Update(elapseSeconds:number,realElapseSeconds:number):void{
        let moudles = GameFrameworkEntry.s_GameFrameworkModules;
        for (let current = moudles.Last; current != null; current = current.Previous)
        {
            current.Value.Update(elapseSeconds,realElapseSeconds);
        }
    }

    public static Shutdown():void{
        let moudles = GameFrameworkEntry.s_GameFrameworkModules;
        for (let current = moudles.Last; current != null; current = current.Previous)
        {
            current.Value.Shutdown();
        }
        moudles.Clear();
    }

    public static GetModule<T extends GameFrameworkModule>(type:{prototype:T}):T{
        let moudles = GameFrameworkEntry.s_GameFrameworkModules;
        let className:string = type.prototype.constructor.name;
        let value =  moudles.ForEach(value => {
            if((<any>value).__proto__.__classname__ == className){
                return true;
            }
            return false;
        })
        if(value){
            return value as T;
        }
        return GameFrameworkEntry.CreateModule(type) as T;
    }


    private static CreateModule<T extends GameFrameworkModule>(classtype):T{
        let module = CreateInstance(classtype);
        if(this.isSub(module)){
            let current:LinkListNode<GameFrameworkModule> = GameFrameworkEntry.s_GameFrameworkModules.First;
            while (current != null)
            {
                if (module.Priority > current.Value.Priority)
                {
                    break;
                }

                current = current.Next;
            }

            if (current != null)
            {
                GameFrameworkEntry.s_GameFrameworkModules.AddBefore(current, module);
            }
            else
            {
                GameFrameworkEntry.s_GameFrameworkModules.AddLast(module);
            }
            return module as T;
        }
        throw new Error("T is not extend GameFrameworkModule");
    }
    private static isSub(instance):instance is GameFrameworkModule
    {
        return instance.baseName == "GameFrameworkModule";
    }

}